/************************************************************************
 * <br>
 * <ul>
 * <li>版权所有：唐山弘川科技有限公司 2009－2020</li>
 * <li>创建日期：2009-8-10</li>
 * <li>初始作者：刘川</li>
 * </ul>
 * <ul>
 * <b>修订历史</b>
 * <li>1、</li>
 * </ul>
 ***********************************************************************/
package com.hy.enterprise.framework.lang ;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

/**
 * <ul>
 * <li>设计作者：刘川</li>
 * <li>设计日期：2009-8-10</li>
 * <li>设计时间：下午02:05:26</li>
 * <li>设计目的：</li>
 * </ul>
 * <ul>
 * <b>修订历史</b>
 * <li>1、</li>
 * </ul>
 */
public class WeakIdentityHashMap < K , V >
{
	private static class IdentityWeakReference < T > extends WeakReference < T >
	{
		private final int	hashCode ;

		/**
		 * 构造函数
		 * 
		 * @param object
		 */
		IdentityWeakReference (
		                        T object )
		{
			this (
			       object ,
			       null ) ;
		}

		/**
		 * 构造函数
		 * 
		 * @param object
		 * @param referenceQueue
		 */
		IdentityWeakReference (
		                        T object ,
		                        ReferenceQueue < T > referenceQueue )
		{
			super (
			        object ,
			        referenceQueue ) ;
			this.hashCode =
			                ( object == null )
			                                  ? 0
			                                  : System
			                                          .identityHashCode ( object ) ;
		}

		/**
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@ SuppressWarnings ( "unchecked" )
		@ Override
		public boolean equals (
		                        Object object )
		{
			if ( this == object )
			{
				return true ;
			}
			if ( ! ( object instanceof IdentityWeakReference ) )
			{
				return false ;
			}
			IdentityWeakReference < T > otherIdentityWeakReference =
			                                                         ( IdentityWeakReference < T > ) object ;
			T got =
			        this
			            .get ( ) ;
			return ( ( got != null ) && ( got == otherIdentityWeakReference
			                                                               .get ( ) ) ) ;
		}

		/**
		 * @see java.lang.Object#hashCode()
		 */
		@ Override
		public int hashCode ( )
		{
			return this.hashCode ;
		}
	}

	private final Map < WeakReference < K > , V >	map	         =
	                                                               new HashMap < WeakReference < K > , V > ( ) ;

	private final ReferenceQueue < K >	          referenceQueue	=
	                                                                  new ReferenceQueue < K > ( ) ;

	private void expunge ( )
	{
		Reference < ? extends K > reference ;
		while ( ( reference =
		                      this.referenceQueue
		                                         .poll ( ) ) != null )
		{
			this.map
			        .remove ( reference ) ;
		}
	}

	private WeakReference < K > makeReference (
	                                            K referent )
	{
		return new IdentityWeakReference < K > (
		                                         referent ) ;
	}

	private WeakReference < K > makeReference (
	                                            K referent ,
	                                            ReferenceQueue < K > referenceQueue )
	{
		return new IdentityWeakReference < K > (
		                                         referent ,
		                                         referenceQueue ) ;
	}

	public V get (
	               K key )
	{
		this
		    .expunge ( ) ;
		WeakReference < K > keyReference =
		                                   this
		                                       .makeReference ( key ) ;
		return this.map
		               .get ( keyReference ) ;
	}

	public V put (
	               K key ,
	               V value )
	{
		this
		    .expunge ( ) ;
		if ( key == null )
		{
			throw new NullPointerException (
			                                 "空键值" ) ;
		}
		WeakReference < K > keyReference =
		                                   this
		                                       .makeReference (
		                                                        key ,
		                                                        this.referenceQueue ) ;
		return this.map
		               .put (
		                      keyReference ,
		                      value ) ;
	}

	public V remove (
	                  K key )
	{
		this
		    .expunge ( ) ;
		WeakReference < K > keyReference =
		                                   this
		                                       .makeReference ( key ) ;
		return this.map
		               .remove ( keyReference ) ;
	}
}
